﻿using AutoMapper;
using Practice.DTO;
using Practice.PH4_2104A.IRepository;
using Practice.PH4_2104A.IService;
using Practice.PH4_2104A.Shopping.SevenLayerFramework.Domin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Practice.Service
{
    public class SKUService : ISKUService
    {

        ISPURepository _spuRepository;
        ISPUSpecRepository _spupecRepository;
        ISPUSpecValueRepository _spuValueRepository;
        ISKURepository _skuRepository;
        ISKUImageRepository _skuImageRepository;
        IUnitOfWork _unitOfWork;
        IMapper _map;

        public SKUService(ISPURepository spuRepository, ISPUSpecRepository spupecRepository,
            ISPUSpecValueRepository spuValueRepository, ISKURepository skuRepository,
            ISKUImageRepository skuImageRepository, IUnitOfWork unitOfWork, IMapper map)
        {
            _spuRepository = spuRepository;
            _spupecRepository = spupecRepository;
            _spuValueRepository = spuValueRepository;
            _skuRepository = skuRepository;
            _skuImageRepository = skuImageRepository;
            _unitOfWork = unitOfWork;
            _map = map;
        }

        #region 添加商品
        /*
         * 1、添加商品，影响到几个表?
         *  spu表
         *  sku表
         *  spu的规格表
         *  spu的规格对应的规格值表
         *  sku的图片表
         *  
         *  
         *  事务：执行两条及以上的非select sql语句，要么全都成功，要么全都不成功。成功则提交事务，失败则回滚事务
         *  使用事务的步骤：开启、提交事务、回滚事务
         *  事务的特性：一致性、原子性、持久性、隔离性
         *  事务的隔离级别：读已提交、读未提交、可重复读、可串行化
         * **/

        public void Insert(ProductInputDTO dto)
        {
            using (var tran = _unitOfWork.GetDbContext().Database.BeginTransaction())  //1、开启事务
            {
                try
                {
                    /*
                     * 1、我们前台传过来的是dto
                     * 2、后台插入数据需要的是model
                     * 所以需要将dto和model进行转换(映射)。转换方式有二种：1）手动。2）自动（Automapper）
                     * 
                     * 自动映射Automapper的使用
                     * 1、安装包:Automapper和DI包
                     * 2、在使用的地方，注入IMapper
                     * 
                     * 3、添加配置文件
                     * 4、注册这个配置文件
                     * **/
                    #region 具体业务实现

                    #region //添加spu表
                    //Map<TSource,TDestinace>  源数据类型、目标数据类型
                    //T:表示泛型，指一切数据类型
                    var spu = _map.Map<ProductInputDTO, SPUModel>(dto);
                    spu.Id = Guid.NewGuid();

                    _spuRepository.Insert(spu);

                    #endregion

                    #region //添加spu规格表 --多个规格，所以用list

                    var spuSpecs = _map.Map<List<ProductSpecInputDTO>, List<SPUSpecModel>>(dto.Specs);
                    spuSpecs.ForEach(x => { x.SpuId = spu.Id; });
                    //var spuSpecs = new List<SPUSpecModel>();
                    //spuSpecs.Add(new SPUSpecModel
                    //{
                    //    SpecName = "",
                    //    SpuId = spu.Id

                    //});
                    _spupecRepository.Insert(spuSpecs);
                    #endregion

                    #region //添加spu规格对应的规格值表 --规格值也有多个，所以用list

                    //var spuSpecValues = new List<SPUSpecValueModel>();
                    //spuSpecValues.Add(new SPUSpecValueModel
                    //{
                    //    SpecValue = "",
                    //    SpuSpecId = ""
                    //});

                    //_spuValueRepository.Insert(spuSpecValues);
                    #endregion

                    #region //添加sku表

                    var skus = _map.Map<List<ProductSKUInputDTO>, List<SKUModel>>(dto.Skus);
                    skus.ForEach(x =>
                    {
                        x.SpuId = spu.Id;

                    });

                    _skuRepository.Insert(skus);
                    #endregion

                    #region //添加sku对应的图片表
                    int index = 0;
                        var skuImgs = new List<SKUImageModel>();
                    dto.Skus.ForEach(x =>
                    {
                        x.Images.ForEach(p =>
                        {
                            skuImgs.Add(new SKUImageModel
                            {
                                SkuId = skus[index].Id,
                                Path = p
                            });
                        });
                        index++;
                    });

                    //var images = new List<SKUImageModel>();
                    //images.Add(new SKUImageModel
                    //{
                    //    SkuId = ""
                    //    Path = "",
                    //});
                    _skuImageRepository.Insert(skuImgs);
                    #endregion


                    _unitOfWork.SaveChanges();
                    #endregion

                    tran.Commit(); //2、提交事务
                }
                catch (Exception)
                {
                    tran.Rollback();//3、回滚事务
                    throw;
                }
            }
        }

        #endregion


        public IQueryable<SKUModel> GetAll()
        {
            return _skuRepository.GetAll();
        }

    }
}
